package com.lagou.minicat.mapper;

import com.lagou.minicat.container.Context;
import com.lagou.minicat.container.Host;
import com.lagou.minicat.container.Wrapper;
import com.lagou.minicat.servlet.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName Mapper
 * @Description
 * @Author playboy
 * @Date 2021/5/22 2:13 下午
 * @Version 1.0
 **/
public class Mapper {
	private static Logger log = LoggerFactory.getLogger(Mapper.class);

	volatile List<MappedHost> mappedHosts = new ArrayList<>();

	/**
	 * 在这里实现路径的匹配，找到对应的host，context，和wapper
	 * 我认为mapped类的意义就是将host和host与context之间关系解耦，
	 * host中是host的真正的有意义的参数，MappedHost则维护了host与context之间的关系
	 *
	 * @param request
	 */
	public void map(Request request) {
		String host = request.getHost();
		String url = request.getUrl();
		MappingData mappingData = new MappingData();
		request.setMappingData(mappingData);

		//查找host
		MappedHost mappedHost = null;
		for (MappedHost mappedHostTemp : mappedHosts) {
			if (mappedHostTemp.name.equals(host)) {
				mappedHost = mappedHostTemp;
				break;
			}
		}
		if (mappedHost == null) {
			request.setDynamic(false);
			return;
		}
		mappingData.setHost(mappedHost.object);

		//查找匹配的context
		MappedContext mappedContext = null;
		for (MappedContext mappedContextTemp : mappedHost.mappedContexts) {
			//查找context
			if (url.startsWith(mappedContextTemp.name)) {
				mappedContext = mappedContextTemp;
				break;
			}
		}
		if (mappedContext == null) {
			request.setDynamic(false);
			return;
		}
		mappingData.setContext(mappedContext.object);

		//查找匹配的servlet 暂时只实现了精确匹配
		MappedWrapper mappedWrapper = null;
		for (MappedWrapper mappedWrapperTemp : mappedContext.mappedWrappers) {
			String subUrl = url.substring(mappedContext.name.length(), url.length());
			if (subUrl.equals(mappedWrapperTemp.name)) {
				mappedWrapper = mappedWrapperTemp;
				break;
			}
		}
		if (mappedWrapper == null) {
			request.setDynamic(false);
			return;
		}
		mappingData.setWrapper(mappedWrapper.object);
	}


	public void addHost(String name, Host host) {
		MappedHost mappedHost = new MappedHost(name, host);
		mappedHosts.add(mappedHost);
	}

	public void addContext(String name, Context context, Host host) {
		for (MappedHost mappedHost : mappedHosts) {
			if (mappedHost.object.equals(host)) {
				MappedContext mappedContext = new MappedContext(name, context);
				mappedHost.mappedContexts.add(mappedContext);
				return;
			}
		}
	}

	public void addWrapper(Host host, Context context, String name, Wrapper wrapper) {
		for (MappedHost mappedHost : mappedHosts) {
			if (mappedHost.object.equals(host)) {
				for (MappedContext mappedContext : mappedHost.mappedContexts) {
					if (mappedContext.object.equals(context)) {
						MappedWrapper mappedWrapper = new MappedWrapper(name, wrapper);
						mappedContext.mappedWrappers.add(mappedWrapper);
						return;
					}
				}
			}
		}
	}


	/**
	 * 这个类的作用其实就是相当于一个T对象和它的child之间的关系维护，将这个关系统一的抽象出来，和真正的实体解耦
	 *
	 * @param <T>
	 */
	protected abstract static class MappedElement<T> {
		String name;
		T object;

		public MappedElement(String name, T object) {
			this.name = name;
			this.object = object;
		}
	}

	protected static final class MappedHost extends MappedElement<Host> {
		List<MappedContext> mappedContexts;

		public MappedHost(String name, Host object) {
			super(name, object);
			this.mappedContexts = new ArrayList<>();
		}
	}

	protected static final class MappedContext extends MappedElement<Context> {
		List<MappedWrapper> mappedWrappers;

		public MappedContext(String name, Context object) {
			super(name, object);
			this.mappedWrappers = new ArrayList<>();
		}
	}

	protected static final class MappedWrapper extends MappedElement<Wrapper> {
		public MappedWrapper(String name, Wrapper object) {
			super(name, object);
		}
	}
}
